<?php
namespace Api\Rds;

/**
 * 流程引擎交互api封装.
 *
 *  Flow::start  开启一个流程引擎
 *  Flow::next   正常推一个流程节点
 *  Flow::update 修改当前节点的数据
 *  Flow::branch 推向分支(异常)流程,比如某操作失败,拒绝等状态
 *  Flow::replay 重新推向某节点
 *
 *  Flow::getInfo  获取到busi_id最新的节点信息
 *  Flow::getLog   查询一个busi_id的所有记录
 *
 *
 */

class Flow {

    const NEXT = 1; //向下推送节点
    const UPDATE = 2; //只是修改数据
    const REPLAY = 3; //重推某流程,重新执行某流程
    const BRANCH = 4; //推入异常,分支流程
    const START = 5; //加入到流程


    /**
     * 开始节点
     * @param string $busi_id  业务唯一id
     * @param string $tmpl_id  模板id
     * @param array $data 节点数据主体
     * @return boolean
     */
    public function start($busi_id, $tmpl_id, array $data) {
        return $this->submit($busi_id, $tmpl_id, null, $data, self::START, null);
    }

    /**
     * 推向下一节点, now_node_key 表示当前节点key,流程引擎会根据配置自动往下推
     * @param string $busi_id
     * @param int $tmpl_id
     * @param string $now_node_key
     * @param array $data
     * @return boolean
     */
    public function next($busi_id, $tmpl_id, $now_node_key, array $data) {
        return $this->submit($busi_id, $tmpl_id, $now_node_key, $data, self::NEXT, null);
    }

    /**
     * 修改当前节点数据,做数据修改, 只能修改当前的节点.
     * @param string $busi_id
     * @param int $tmpl_id
     * @param string $now_node_key  要修改的节点
     * @param array $data
     * @return boolean
     */
    public function update($busi_id, $tmpl_id, $now_node_key, array $data) {
        return $this->submit($busi_id, $tmpl_id, $now_node_key, $data, self::UPDATE);
    }

    /**
     * 异常,分支节点, 异常节点可以由任意节点推至.
     * @param string $busi_id
     * @param int $tmpl_id
     * @param string $branch_key  要推向的异常节点
     * @param array $data
     * @return boolean
     */
    public function branch($busi_id, $tmpl_id, $branch_key, array $data) {
        return $this->submit($busi_id, $tmpl_id, null, $data, self::BRANCH, $branch_key);
    }

    /**
     * 重新执行某个节点, 比如需要从某异常节点推至正常节点.或者重新执行某节点
     * 必须指定当前节点和需要重推的节点
     * @param string $busi_id
     * @param int $tmpl_id
     * @param string $now_node_key
     * @param array $data
     * @param string $replay_key
     * @return boolean
     */
    public function replay($busi_id, $tmpl_id, $now_node_key, array $data, $replay_key) {
        return $this->submit($busi_id, $tmpl_id, $now_node_key, $data, self::REPLAY, $replay_key);
    }

    /**
     * 查询busi_id当前执行节点数据情况
     * @param string $busi_id
     * @return array
     * @throws \S\Exception
     *
     * return array(
     *  'tmpl_id' => 1,
     *  'node_key' => 'Start',
     *  'busi_id' => 'credit_100',
     *  'exec_num' => 1, //执行次数
     *   'data' => array(),
     * )
     */
    public function getInfo($busi_id){
        $url = '/flow/query/info';
        $params = array(
            'app_id' => self::getAppId(),
            'busi_id' => $busi_id,
        );

        $util = new Util();
        $ret = $util->request($url, $params);
        if ($util->code != Util::SUCC_CODE) {
            throw new \S\Exception($util->message, $util->code);
        }
        return $ret['data'];
    }

    /**
     * 查询某busi_id所有的历史log
     * @param string $busi_id
     * @return array
     * @throws \S\Exception
     *
     * return array(
     *   array(), //getInfo接口相同
     *   array()
     * )
     */
    public function getLog($busi_id){
        $url = '/flow/query/flow';
        $params = array(
            'app_id' => self::getAppId(),
            'busi_id' => $busi_id,
        );

        $util = new Util();
        $ret = $util->request($url, $params);
        if ($util->code != Util::SUCC_CODE) {
            throw new \S\Exception($util->message, $util->code);
        }
        return $ret['data'];
    }


    /**
     * 推送数据
     * @param string $busi_id
     * @param string $tmpl_id
     * @param string $now_node_key
     * @param array $data
     * @param int $action 向下推送还是修改数据
     * @param string $target_node_key 目标节点,包括重推或者
     * @return boolean
     * @throws \S\Exception
     */
    private function submit($busi_id, $tmpl_id, $now_node_key, array $data, $action, $target_node_key = null) {
        $url = '/flow/submit';
        $data = array(
            'busi_id' => $busi_id,
            'app_id' => self::getAppId(),
            'tmpl_id' => $tmpl_id,
            'now_node_key' => $now_node_key,
            'data' => json_encode($data),
            'action' => $action,
            'target_node_key' => $target_node_key,
        );

        $util = new Util();
        $util->request($url, $data);
        if ($util->code != Util::SUCC_CODE) {
            throw new \S\Exception($util->message, $util->code);
        }
        return true;
    }


    public static function getAppId() {
        return 0;
    }
}